#include "action_manage.h"
#include "string.h"
#include <sys/ipc.h>
#include <sys/msg.h>
#include <unistd.h>

#include "/home/hcgy/Documents/esm6800h/app/msg_def.h"

CActionMange * g_ptrEleCtlManage;
CActionMange * g_ptrModuleManage;

CActionMange::CActionMange()
{
    m_listActionHead = NULL;
    m_ptrTail = 0;
    m_numAct = 0;
}

CActionMange::~CActionMange()
{
    action_desc * ptrActNode = m_listActionHead;
    action_desc * ptrActNodeTemp = NULL;
    while(ptrActNode)
    {
        ptrActNodeTemp = ptrActNode;
        ptrActNode = ptrActNode->next;

        memset(ptrActNodeTemp,0,sizeof(action_desc));
        delete ptrActNodeTemp;
        ptrActNodeTemp = NULL;
    }
    m_numAct = 0;
}

void CActionMange::register_action(int actId, int actStatus)
{
   action_desc * ptrActNode = new action_desc;

   memset(ptrActNode,0,sizeof(action_desc));
   ptrActNode->actId = actId;
   ptrActNode->status = actStatus;
   ptrActNode->next = NULL;


   if(m_listActionHead==NULL)
   {
      //std::cout<<"set m_listActionHead to "<<ptrActNode<<std::endl;
      m_listActionHead = ptrActNode; 
      m_ptrTail = ptrActNode;
   }
   else
   {
       m_ptrTail->next = ptrActNode;
       m_ptrTail = ptrActNode;
   }

   m_numAct++;

}

action_desc * CActionMange::findNodeById(int actId)
{
    action_desc * ptrActNode = m_listActionHead;
    action_desc * ptrActNodeTemp = NULL;
    while(ptrActNode)
    {

        if(ptrActNode->actId == actId)
        {
           ptrActNodeTemp = ptrActNode;
           break;
        }
        ptrActNode = ptrActNode->next;        
    }

    return ptrActNodeTemp;
}


void CActionMange::setActStatus(int actId, int actStatus)
{
    std::cout << "set actid:"<<actId<<" status:"<<actStatus<<std::endl;

    action_desc * ptrActNode = findNodeById(actId);

    
    if(NULL == ptrActNode)
    {
        //std::cout << "register actid:"<<actId<<" status:"<<actStatus<<std::endl;
        register_action(actId,actStatus);
    }
    else
    {
        ptrActNode->status = actStatus;
    }
}

int CActionMange::getActStatus(int actId,int* statusCodeOut, int * errorNum)
{
    action_desc * ptrActNode = findNodeById(actId);
    
    if(NULL==ptrActNode)
    {
        return ACT_FINISHED;
    }
    else
    {
        //std::cout<<"find in getActStatus success actId:"<<actId<<std::endl;
        *statusCodeOut = ptrActNode->statusCode;
        * errorNum = ptrActNode->errorNum;
        return ptrActNode->status;
    }
}

int CActionMange::getActStatus(int actId)
{
    action_desc * ptrActNode = findNodeById(actId);
    if(NULL==ptrActNode)
    {
        return ACT_FINISHED;
    }
    else
    {
        return ptrActNode->status;
    }
}


void CActionMange::updateAction(void * dataRecv)
{

    action_desc * ptrActNode = m_listActionHead;
    action_desc * ptrActNodeTemp = NULL;

    msgAck * ptrData = (msgAck *)dataRecv;
    

    int actId = ptrData->moduleId;
    if(actId == -1)
    {
       actId = ptrData->sid;
    }

     //std::cout<<"enter in updateAction, actId:"<<actId
     //<<" moduleId:"<<ptrData->moduleId<<" sid:"<<ptrData->sid<<std::endl;

    // std::cout<<"ptrActNode:"<<ptrActNode
    // <<" m_listActionHead:"<<m_listActionHead<<std::endl;
    while(ptrActNode)
    {
        //std::cout<<"update actId:"<<ptrActNode->actId<<" in list"<<std::endl;
        if(ptrActNode->actId == actId)
        {           
           break;
        }
        ptrActNodeTemp = ptrActNode;
        ptrActNode = ptrActNode->next;        
    }

    if(NULL==ptrActNode)
    {
        std::cout<<"in updateAction, find failed, actId:"
        <<actId<<" moduleId:"<<ptrData->moduleId<<" sid:"<<ptrData->sid<<std::endl;
        return;
    }
    else
    {
        std::cout << "update actid:"<<actId<<" status:"<<ACT_FINISHED<<std::endl;
        ptrActNode->status = ACT_FINISHED;
        ptrActNode->statusCode = ptrData->statusCode;
        ptrActNode->errorNum = ptrData->errorNum;
    }

    //delete the node maybe need
    // if(ptrActNodeTemp!=NULL)
    // {
    //     ptrActNodeTemp->next = ptrActNode->next;

    // }
    // else
    // {
    //     //the target node is the first.
    //     m_listActionHead = m_listActionHead->next;
    // }

    // memset(ptrActNode,0,sizeof(action_desc));
    // delete ptrActNode;   

}
int appAckRecvexitFlag = 0;

void * funcRecvAck(void * param)
{
    int msgId = *((int *)param);

    msgQueueAck ackMsg;
    int ret = 0;
    int sid = 0;
    int moduleId = -1;
    while(!appAckRecvexitFlag)
    {
        ret = msgrcv( msgId, &ackMsg, sizeof(msgAck) ,QUEUE_MSG_TYPE_GRPC,IPC_NOWAIT );
        if(ret>0)
        {
            printf("receive ack success!\n");
            if(ackMsg.msg.moduleId == -1)
            {
                g_ptrEleCtlManage->updateAction(&(ackMsg.msg));
            }
            else
            {
                g_ptrModuleManage->updateAction(&(ackMsg.msg)); 
            }
                
       }
       usleep(2000);
    }
}